package http

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/mssola/user_agent"
	"github.com/sirupsen/logrus"
	"net/http"
	"os"
	"runtime/debug"
	"time"
)

func Logger(logEntry *logrus.Entry, withUA bool) gin.HandlerFunc {
	return func(c *gin.Context) {
		start := time.Now()
		defer func() {
			if err := recover(); err != nil {
				stackInfo := string(debug.Stack())
				logEntry.Errorf("got panic panic:%+v, stack:%v", err, stackInfo)
			}

			path := c.Request.URL.Path
			url := c.Request.URL.RequestURI()

			since := time.Since(start).Milliseconds()
			statusCode := c.Writer.Status()
			clientIP := c.ClientIP()
			hostname, err := os.Hostname()
			if err != nil {
				hostname = "unknown"
			}
			var errMsg string
			if em, ok := c.Get(CtxErrorKey); ok {
				errMsg = em.(string)
			}

			entry := logEntry.WithFields(logrus.Fields{
				"hostname":   hostname,
				"status": 	  statusCode,
				"statusMsg":  http.StatusText(statusCode),
				"errMsg":     errMsg,
				"since":      fmt.Sprintf("%dms", since), // time to process
				"client":     clientIP,
				"path":       path,
				"url":        url,
			})
			if withUA {
				clientUserAgent := c.Request.UserAgent()
				referer := c.Request.Referer()
				ua := user_agent.New(clientUserAgent)
				engineName, engineVersion := ua.Engine()
				browserName, browserVersion := ua.Browser()
				entry = entry.WithFields(logrus.Fields{
					"clientIP":           clientIP,
					"referer":            referer,
					"userAgent":          clientUserAgent,
					"ua-mobile":          ua.Mobile(),
					"ua-bot":             ua.Bot(),
					"ua-mozilla":         ua.Mozilla(),
					"ua-platform":        ua.Platform(),
					"ua-os":              ua.OS(),
					"ua-engine-name":     engineName,
					"ua-engine-version":  engineVersion,
					"ua-browser-name":    browserName,
					"ua-browser-version": browserVersion,
				})
			}
			if len(c.Errors) > 0 {
				entry.Warn(c.Errors.ByType(gin.ErrorTypePrivate).String())
			} else {
				entry.Info("")
			}
		} ()
		c.Next()
	}
}
